package cn.wyl.basic.Interceptor;

import cn.wyl.basic.jwt.JwtUtils;
import cn.wyl.basic.jwt.Payload;
import cn.wyl.basic.jwt.RsaUtils;
import cn.wyl.system.annotation.PreAuthorize;
import cn.wyl.user.domain.Logininfo;
import cn.wyl.user.dto.LoginData;
import cn.wyl.user.mapper.LogininfoMapper;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 后端登录拦截器
 * 拦截前端Axious需要后端处理的异步请求
 */
@Component //LoginInterceptor交给spring管理才能注入属性
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    LogininfoMapper logininfoMapper;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("后端登录拦截器");
        String token=null;

        String url=request.getRequestURL().toString();
        if (url.contains("shop/export") ){
             token = url.substring(url.lastIndexOf("/" )+1);
        }else {

            //1.从请求头中获取token
            token = request.getHeader("token");
        }

        /*System.out.println("后端登录拦截器");
        System.out.println(token);*/

        //3.如果有token，通过token获取redis的登录信息
        if (token != null) {
            //获取公钥
            PublicKey publicKey = RsaUtils.getPublicKey(RsaUtils.class.getClassLoader().getResource("auth_rsa.pub").getFile());
            try {
                //将jwtToken解析成想要的数据：LoginData
                Payload<LoginData> payload = JwtUtils.getInfoFromToken(token, publicKey, LoginData.class);
                if (payload != null){//成功解密token，且没有过期
                    //获取登录信息对象
                    Logininfo logininfo = payload.getLoginData().getLogininfo();
                    //如果是用户 - 放行
                    if (logininfo.getType() == 1) { return true; }
                    //如果是后端管理员 - 验证权限【后端管理员 - 角色不一样 - 权限不一样】
                    //获取当前接口上注解里的sn - handler - 获取注解@PreAuthorize - 获取注解里面的sn
                    HandlerMethod handlerMethod = (HandlerMethod) handler; //就是接收请求的接口上的方法
                    PreAuthorize annotation = handlerMethod.getMethodAnnotation(PreAuthorize.class);//获取方法上的PreAuthorize注解
                    if (annotation == null) {//如果当前接口方法上没有这个注解 - 不需要校验权限 - 直接放行

                        return true;
                    }else{//获取该方法PreAuthorize注解上的sn
                        String sn = annotation.sn();
                        //根据logininfo_id获取当前登录人的所有权限 - sn
                        List<String> sns = logininfoMapper.loadPermissionsByLogininfoId(logininfo.getId());
                        //有权限放行
                        if(sns.contains(sn)){return true;}
                        else {//else会经过后置拦截器，可以在axios后置拦截器中判断弹出错误框
                            response.setContentType("application/json;charset=UTF-8");
                            response.getWriter().println("{\"success\":false,\"msg\":\"noPermission\"}");
                            //拦截
                            return false;
                        }
                    }

                }

            } catch (ExpiredJwtException e) {//45行发生过期异常
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println("{\"success\":false,\"msg\":\"timeout\"}");
                return false;
            }catch (Exception e){
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println("{\"success\":false,\"msg\":\"otherException\"}");
                return false;
            }




        }

        // 如果没有token即未登录过，或logininfo==null即登录失效，直接拦截 响应前端 - 跳转到登录页面
        //跳转到登录页面 - 后端跳不了，因为后端项目没有页面 - 放在前端跳转
        //告诉浏览器我要给你响应一个json数据，编码集为utf-8
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println("{\"success\":false,\"msg\":\"noLogin\"}");
        //拦截
        return false;
    }


}
